#include <iostream>
#include <functional>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <cstdbool>
#include <cstdlib>
#include <cstring>

// 验证写端不但不写,还把写端关闭,读端一直读会发生什么???
int main()
{
    int pipefd[2]={0};

    pipe(pipefd);

    pid_t id=fork();

    if(id==0)
    {
        // 关闭写端
        close(pipefd[1]);

        char buff[1024]={'\0'};

        while(true)
        {
            read(pipefd[0],buff,sizeof(buff));
        }
    }

    // 关闭读端
    close(pipefd[0]);

    // 关闭写端
    close(pipefd[1]);

    int status=0;

    waitpid(id,&status,0);

    std::cout<<" 父进程pid: "<<getpid()<<" 子进程pid: "<<id<<" 退出信号: "<<(status&0x7f)<<" core_dump: "<<((status>>7)&1)<<std::endl;
    // 读端一直在等???

    return 0;
}

// // 验证读端不但不读,还把读端关闭,写端一直写会发生什么???
// int main()
// {
//     int pipefd[2]={0};

//     pipe(pipefd);

//     pid_t id=fork();

//     if(id==0)
//     {
//         // 关闭读端
//         close(pipefd[0]);

//         char buff[1024]="abcdef";

//         // 子进程一直写
//         while(true)
//         {
//             write(pipefd[1],buff,strlen(buff)+1);
//         }
//     }

//     // 关闭写端
//     close(pipefd[1]);

//     // 关闭读端
//     close(pipefd[0]);

//     int status=0;

//     waitpid(id,&status,0);

//     std::cout<<" 父进程pid: "<<getpid()<<" 子进程pid: "<<id<<" 退出信号: "<<(status&0x7f)<<" core_dump: "<<((status>>7)&1)<<std::endl;

//     // 退出信号: 13 core_dump: 0
//     // 13) SIGPIPE : Broken pipe: write to pipe with no

//     return 0;
// }

// // 初始硬件引起的信号
// void CatchSig(int signum)
// {
//     std::cout<<" 处理信号编号为: "<<signum<<" 处理进程pid为: "<<getpid()<<std::endl;
// }
// int main()
// {
//     sleep(1);
//     signal(SIGFPE,CatchSig);
//     //signal(SIGABRT,CatchSig);

//     int i=3;
//     i/=0;

//     //abort();

//     while(true)
//     {
//     }  

//     return 0;
// }

// // 了解alarm接口
// static int count=0;

// using CatchSigHandler_t=std::function<void(int)>;
// //typedef std::function<void(int)> _t;

// // 定时器
// void CatchSig(int signum)
// {
//     std::cout<<count<<std::endl;
//     std::cout<<"处理信号编号为: "<<signum<<"处理进程pid为: "<<getpid()<<std::endl;
//     //exit(1);
//     alarm(1);
// }

// int main()
// {
//     signal(SIGALRM,&CatchSig);
//     // unsigned int alarm(unsigned int seconds);
//     // alarm()安排SIGALRM信号以秒为单位传递给调用进程
//     // SIGALRM      14       Term    Timer signal from alarm
//     alarm(1); // 设定了一个闹钟，这个闹钟一旦触发，就自动移除了

//     while(true)
//     {
//         count++;
//         //std::cout<<++count<<std::endl;
//     }

//     return 0;
// }

// // 如何通过系统调用产生信号
// int main(int argc,char** argv,char** env)
// {
//     // 给自身发送相应的信号
//     // int raise(int sig);--->kill(getpid(),sig);

//     // 给自身发送SIGABRT(6)中止信号
//     // Abort signal from abort
//     // void abort(void);--->int raise(6);--->kill(getpid(),6);

//     pid_t id=fork();

//     if(id==0)
//     {
//         sleep(1);

//         //raise(8);
//         abort();
//     }

//     int status=0;

//     waitpid(id,&status,0);
//     std::cout<<" 父进程pid: "<<getpid()<<" 子进程pid: "<<id<<" 退出信号: "<<(status&0x7f)<<" core_dump: "<<((status>>7)&1)<<std::endl;
    
//     // // 给对应进程发送信号
//     // if(argc!=3)
//     // {
//     //     std::cout<<"./signal signalnumber procid"<<std::endl;
//     //     exit(1);
//     // }
//     // // int kill(pid_t pid, int sig);
//     // // 发送成功返回0,否则返回-1并设置errno

//     // int signalnumber=atoi(argv[1]);
//     // int procid=atoi(argv[2]);

//     // kill(procid,signalnumber);

//     // // 查看命令行参数与环境变量有些什么
//     // for(int i=0;i<argc;i++)
//     // {
//     //     // ./signal -a -b -c
//     //     std::cout<<argv[i]<<std::endl;
//     // }

//     // for(int i=0;env[i]!=nullptr;i++)
//     // {
//     //     std::cout<<env[i]<<std::endl;
//     // }

//     return 0;
// }


// // 了解进程等待的退出状态status中的core_dump
// // status: |00000000     | 0 |     0000000|
// //           退出码    core_dump    退出信号

// // core: 核心转储 
// // 如何设置核心转储: ulimit -a : core file size          (blocks, -c) 0
// // ulimit -c size 

// // 核心存储被设置了(也即进程的core_dump为1)+进程收到Action为core的信号
// // 进程在(异常)退出的时候会生成core.pid文件(相关的内存数据)
// // core.pid文件能在debug的时候快速定位错误
// // 在gdb中:core-file core.pid
// int main()
// {
//     pid_t id=fork();
    
//     if(id==0) // 子进程
//     {
//         //std::cout<<"子进程pid: "<<getpid()<<std::endl;

//         // 当核心转储没有被打开时,不管是term还是core信号,其接收的对应进程的core_dump都是0
//         // 只有核心转储被打开并且进程接收到的信号是core时,其进程的退出信息中的core_dump才是1(也即会生成core.pid文件)
//         // >为什么在生产环境中,核心转储会被关闭?
//         // >避免出现异常时,生成的core.pid文件撑暴磁盘
//         while(true) sleep(1);

//         int num=100;

//         num/=0; // 除零会触发段错误:SIGFPE(8)   core   Floating point exception

//         // gdb通过core.pid文件定位到的错误:
//         // Core was generated by ./signal.
//         // Program terminated with signal 8, Arithmetic exception.
//     }

//     int status=0;

//     waitpid(id,&status,0);

//     std::cout<<" 父进程pid: "<<getpid()<<" 子进程pid: "<<id<<" 退出信号: "<<(status&0x7f)<<" core_dump: "<<((status>>7)&1)<<std::endl;

//     return 0;
// }

// // 认识signal函数: signal函数，仅仅是修改进程对特定信号的后续处理动作，不是直接调用对应的处理动作
// void CatchSig(int signum)
// {
//     std::cout<<"处理信号编号为: "<<signum<<"处理进程pid为: "<<getpid()<<std::endl;
// }

// int main(int,char**,char**)
// {
//     // typedef void (*sighandler_t)(int);
//     // sighandler_t signal(int signum, sighandler_t handler);
//     // signum: 信号编号 handler: 函数指针(回调函数)

//     // 1.SIGINT(2): Interrupt from keyboard 触发信号2(SIGINT)的方式: Ctrl+c or kill -2 pid

//     // 设置进程对特定信号的处理方式
//     signal(SIGINT,CatchSig); // 如果后续没有任何SIGINT信号产生，CatchSig永远也不会被调用

//     // 2.SIGQUIT(3): Quit from keyboard
//     signal(SIGQUIT,CatchSig);

//     while(true)
//     {
//         std::cout<<"正在运行,进程pid: "<<getpid()<<std::endl;
//         sleep(1);
//     }

//     return 0;
// }